use actix_web::{
    Error, HttpResponse,
    dev::{Service, ServiceRequest, ServiceResponse, forward_ready},
    error::InternalError,
};
use futures_util::future::LocalBoxFuture;

use crate::define::{ApiResponse, BaseError};

pub struct ErrorService<S> {
    service: S,
}

impl<S, B> Service<ServiceRequest> for ErrorService<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;

    forward_ready!(service); // 复用原始服务的 poll_ready 逻辑

    fn call(&self, request: ServiceRequest) -> Self::Future {
        // 关键：拆分请求为头部和 payload，避免克隆整个ServiceRequest
        let (req_head, payload) = request.into_parts();
        // 克隆请求头部（HttpRequest实现了Clone）
        let cloned_head = req_head.clone();

        // 重新组合请求用于原始服务调用
        let service_req = ServiceRequest::from_parts(req_head, payload);
        let fut = self.service.call(service_req);

        Box::pin(async move {
            fut.await.map_err(|err| {
                // 构建错误响应体
                let error_resp = ApiResponse::err(BaseError::InternalError, "Internal Server Error".into());

                // 构建HTTP错误响应
                let http_resp = HttpResponse::InternalServerError().json(error_resp).map_into_boxed_body();

                // 使用克隆的请求头部构建ServiceResponse
                let service_resp = ServiceResponse::new(
                    cloned_head, // 使用克隆的HttpRequest
                    http_resp,
                );

                // 转为Error类型
                InternalError::from_response(err, service_resp.into()).into()
            })
        })
    }
}
